/**
 * 
 */
package at.ac.tuwien.big.esw.ue1;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

/**
 *
 */
public class HotelSPARQLQueries {
	
	private InfModel infModel;
	
	private static HotelSPARQLQueries instance = null;
	
	public static HotelSPARQLQueries newInstance(InputStream is) {
		if (instance == null) {
			instance = new HotelSPARQLQueries(is);
		}
		return instance;
	}
	
	private HotelSPARQLQueries(InputStream is) {
		Model model = ModelFactory.createDefaultModel();
		model.read(is, null, "N3");
		this.infModel = ModelFactory.createRDFSModel(model);
	}

	/**
	 * 
	 */
	public String findHotelsWithMinStars(int minStars) {
		String result = "";
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?hotel ?name ?hasStarrating "
						+ "WHERE {"
						+ "  ?hotel hotel:name ?name."
						+ "  ?hotel hotel:hasStarrating ?hasStarrating."
						+ "  FILTER (?hasStarrating > " + minStars + ")." + "}");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String name = soln.getLiteral("name").getString();
				String stars = soln.getLiteral("hasStarrating").getString();
				result += (result.length() > 0 ? ", " : "") + name + " (" + stars + " Sterne)";
			}
			
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public String findAttractionsAndHotelsNearHotel(String hotelName) {
		String result = "";
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?nearTo ?name "
						+ "WHERE {"
						+ "  ?nearTo  hotel:nearTo ?hotel."
						+ "  ?nearTo  hotel:name ?name."
						+ "  ?hotel hotel:name \"" + hotelName + "\"}");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String name = soln.getLiteral("name").getString();
				result += (result.length() > 0 ? ", " : "") + name;
			}
			
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public boolean isGuestResidedInHotel(String guestName, String hotelName) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String currentDate = dateFormat.format(new Date());

		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?booking ?startDate "
						+ "WHERE {"
						+ "  ?hotel hotel:name \"" + hotelName +"\"."
						+ "  ?hotel hotel:hasBooking ?booking."
						+ "  ?booking hotel:isBookingOfGuest ?guest."
						+ "  ?guest hotel:name \"" + guestName + "\"."
						+ "  ?booking hotel:startdate ?startDate.}");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String startDate = soln.getLiteral("startDate").getString();
				if (startDate.compareTo(currentDate) < 0) {
					return true;
				}
			}
			
		} finally {
			queryExecution.close();
		}
		return false;
	}

	public String findPersonsBookedSmokersRoom() {
		String result = "";
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?person ?name "
						+ "WHERE {"
						+ "  ?booking hotel:isBookingOfGuest ?person."
						+ "  ?booking hotel:bookedRoom ?room."
						+ "  ?room hotel:isSmokingRoom true."
						+ "  ?person hotel:name ?name. }");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String name = soln.getLiteral("name").getString();
				result += (result.length() > 0 ? ", " : "") + name;
			}
			
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public String findWellnessOfferingsBookedBySmokerRoomBookers() {
		String result = "";
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?wellnessOffering ?name "
						+ "WHERE {"
						+ "  ?booking hotel:includesOffer ?wellnessOffering."
						+ "  ?wellnessOffering hotel:name ?name."
						+ "  ?booking hotel:bookedRoom ?room."
						+ "  ?room hotel:isSmokingRoom true. }");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String name = soln.getLiteral("name").getString();
				result += (result.length() > 0 ? ", " : "") + name;
			}
			
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public boolean isRoomXNearRoomY(String roomX, String roomY) {
		boolean result = false;
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "ASK { "
						+ "  ?roomX hotel:hasNeighbourRoom ?roomY."
						+ "  ?roomY hotel:hasNeighbourRoom ?roomX."
						+ "  ?roomX hotel:roomNumber ?roomNumberX."
						+ "  FILTER (?roomNumberX = " + roomX + ")."
						+ "  ?roomY hotel:roomNumber ?roomNumberY."
						+ "  FILTER (?roomNumberY = "+ roomY + ")."
						+ "  ?roomX hotel:isRoomOf ?hotel."
						+ "  ?roomY hotel:isRoomOf ?hotel. }");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			result = queryExecution.execAsk();
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public boolean isGuestXAkinGuestY(String guestX, String guestY) {
		boolean result = false;
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "ASK { "
						+ "  ?guestX hotel:IsRelativeOf ?guestY."
						+ "  ?guestY hotel:IsRelativeOf ?guestX."
						+ "  ?guestX hotel:name \"" + guestX + "\"."
						+ "  ?guestY hotel:name \"" + guestY + "\". }");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			result = queryExecution.execAsk();
		} finally {
			queryExecution.close();
		}
		return result;
	}

	public String findCognateGuestsHaveRoomsSideBySide() {
		String result = "";
		Query query = QueryFactory.create("PREFIX hotel: <http://www.owl-ontologies.com/Ontology1260196108.owl#>"
						+ "SELECT ?guestX ?name "
						+ "WHERE {"
						+ "  ?guestX hotel:IsRelativeOf ?guestY."
						+ "  ?guestX hotel:name ?name."
						+ "  ?guestX hotel:hasBookedBooking ?bookingX."
						+ "  ?bookingX hotel:bookedRoom ?bookedRoomX."
						+ "  ?bookedRoomX hotel:hasNeighbourRoom ?bookedRoomY."
						+ "  ?guestY hotel:IsRelativeOf ?guestX."
						+ "  ?guestY hotel:hasBookedBooking ?bookingY."
						+ "  ?bookingY hotel:bookedRoom ?bookedRoomY."
						+ "  ?bookedRoomY hotel:hasNeighbourRoom ?bookedRoomX. }");
		QueryExecution queryExecution = QueryExecutionFactory.create(query, this.infModel);
		try {
			ResultSet resultSet = queryExecution.execSelect();
			while (resultSet.hasNext()) {
				QuerySolution soln = resultSet.nextSolution();
				String name = soln.getLiteral("name").getString();
				result += (result.length() > 0 ? ", " : "") + name;
			}
			
		} finally {
			queryExecution.close();
		}
		return result;
	}
	

}
